package vnu;

import jade.content.ContentElement;
import jade.content.lang.Codec.CodecException;
import jade.content.onto.OntologyException;
import jade.content.onto.UngroundedException;
import jade.content.onto.basic.Result;
import jade.core.AID;
import jade.core.Agent;
import jade.core.Location;
import jade.core.behaviours.OneShotBehaviour;
import jade.core.behaviours.ParallelBehaviour;
import jade.core.behaviours.SimpleBehaviour;
import jade.core.behaviours.WakerBehaviour;
import jade.lang.acl.ACLMessage;
import jade.lang.acl.MessageTemplate;
import jade.lang.acl.UnreadableException;


import java.io.IOException;
import java.io.Serializable;

import javax.sql.rowset.spi.SyncFactory;

import vocabulary.MyMapVoca;

/**
 * @author NguyenLan
 *
 */

public  class JobAgent extends  Agent implements MyMapVoca,Serializable
{
	
	/**
	 * 
	 */
	private static final long serialVersionUID = 1L;
	private jade.core.AID agentmanagerAID;
	private String agentmanagerAddress;
	private AID target = new AID();
	
@Override
 protected void setup() {
	// TODO Auto-generated method stub
	agentmanagerAddress=AGENT_MANAGER;
	agentmanagerAID= new jade.core.AID(agentmanagerAddress, jade.core.AID.ISLOCALNAME);
	super.setup();
	//seding inform message to managerAgent
	AgentInfo a = new AgentInfo(getAID().getLocalName(), getAID().getName(), getAID().getAddressesArray()[0]);
	notifyCreate(a);
	System.out.println(agentmanagerAID.getName());
}
@Override
public void doMove(Location arg0) {
	// TODO Auto-generated method stub
	notifyMoving(arg0);
	super.doMove(arg0);
}


/**
 * @param location
 * Notify moving to Agent manager when the agent moves
 */

private void notifyMoving(Location locat){
	//sending inform message to managerAgent
	AgentInfo locationAgent = new AgentInfo(getLocalName(), getName(), locat.getAddress());
	
	if (agentmanagerAID == null) {
		System.err.println("Cannot find Manager Agent");
		return;
	}
		ACLMessage message = new ACLMessage(ACLMessage.INFORM);
		try {
			message.setContentObject((Serializable)locationAgent);
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		message.addReceiver(agentmanagerAID);

		send(message);
		System.out.println("Sending request to  Agent manager...");
	}

/**
 * @param agentcreated
 * Notify to Agent manager when an agent is created
 */

private void notifyCreate(AgentInfo agentcreated){
		
		if (agentmanagerAID == null) {
			System.err.println("Cannot find Manager Agent");
			return;
		}
			ACLMessage message = new ACLMessage(ACLMessage.INFORM);
			try {
				message.setContentObject((Serializable)agentcreated);
				message.addReceiver(agentmanagerAID);
				send(message);
				System.out.println("Sending request to Agent manager...");	
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			
	}


/**
 * @param msg
 * Reply not understand when the agent receive a messmage
 */
public void replyNotUnderstood(ACLMessage msg) {
	try {
		ContentElement content = getContentManager().extractContent(msg);
		ACLMessage reply = msg.createReply();
		reply.setPerformative(ACLMessage.NOT_UNDERSTOOD);
		getContentManager().fillContent(reply, content);
		send(reply);
		System.out.println("Not understood receivedMessage");
	} catch (Exception ex) {
		ex.printStackTrace();
	}
}

/**
 * @param name
 * @return ADI - Agent Identifier
 * Searching for interested Job Agent in multi agent system 
 */


class WaitRespond extends ParallelBehaviour{
	/**
	 * 
	 */
	private static final long serialVersionUID = -6814076678871969283L;

	WaitRespond(Agent a) {
		super(a, 1);
		addSubBehaviour(new ReceiveMessage(myAgent));
		addSubBehaviour(new WakerBehaviour(myAgent, 15000) {

			/**
			 * 
			 */
			private static final long serialVersionUID = 1L;

			protected void handleElapsedTimeout() {
				System.err
						.println("Can not received any responds from DataBase Agent!");
			}
		});
	}
		
	}

class ReceiveMessage extends SimpleBehaviour {

	/**
	 * 
	 */
	private static final long serialVersionUID = 1L;
	private boolean isFinished = false;
	boolean ok = false;
	public ReceiveMessage(Agent a) {
		// TODO Auto-generated constructor stub
		super(a);
	}

	@Override
	public void action() {
		// TODO Auto-generated method stub
		ACLMessage receivedDataMsg = receive();
		if (receivedDataMsg == null) {
			block();
			return;
		}
		int receivedPerformative = receivedDataMsg.getPerformative();
		if (receivedPerformative == ACLMessage.NOT_UNDERSTOOD) {
			System.out.println("Message can not understood JobAgent's request!");
		} else if (receivedPerformative == ACLMessage.INFORM) {
			
			System.out.println("Received INFORM message from  "+ receivedDataMsg.getSender() + receivedDataMsg.getContent());
			
		}
			else {
							System.err.println("Received unexpected respond from database Agent");
						}
			
		isFinished = true;
				}

	@Override
	public boolean done() {
		// TODO Auto-generated method stub
		return isFinished;
	}	

}
	
public void sendMessage(ACLMessageX acl){
	
	if (agentmanagerAID == null) {
		System.err.println("Cannot find Manager Agent");
		return;
	}
	ACLMessage messagex = new ACLMessage(ACLMessage.REQUEST);
	try {
		messagex.setContentObject((Serializable)acl);
	} catch (IOException e) {
		// TODO Auto-generated catch block
		e.printStackTrace();
	}
	messagex.addReceiver(agentmanagerAID);
	send(messagex);
	System.out.println("[Job agent] is sending request to Agent manager....");
	addBehaviour(new WaitRespond(this));
}



public AID getTarget(){
	return target;
}
}

